var EJSON = (function makeJSONCOPY() {
    var err = console.error;

    /**
     * v是null或者undefined返回true,否则返回false。
     * 有时候，我们希望if语句能将false视为真值,
     * 只将null或undefined视为假值。
     */
    function isUndef(v) {
        return v === null || v === undefined;
    }

    /** 与isUndef类似 */
    function isDef(v) {
        return v !== null && v !== undefined;
    }

    /** 获取一个数组或类数组对象的length属性 */
    function len(src) {
        return src.length;
    }

    /** 可以被转义的字符 */
    function canBeTransferred(char) {
        return char === '\\' || char === '/' || char === '"' || char === '\'';
    }

    var _toString = Object.prototype.toString;

    /**
     * 获取参数的数据类型，利用Object.prototype.toString.call(v)
     * 得到诸如 [object Array]类的形式，返回后半部分的小写部分。
     * typeof并不能准确的获取一个值的数据类型
    */
    function getRawType(src) {
        return _toString.call(src).slice(8, -1).toLowerCase();
    }

    /** ployfill of push */
    function push(e) {
        this[len(this)] = e;
    }

    /** ployfill of pop */
    function pop() {
        if (len(this) > 0) {
            var top = this[len(this) - 1];
            this.length -= 1;
            return top;
        }
        return null;
    }

    /** 将JSON字符串解析成JS对象的函数 */
    function makeParser() {
        var nReg = /(0|1|2|3|4|5|6|7|8|9)/;

        /** 0-9? */
        function isDigit(v) {
            return nReg.test(v);
        }

        /** 是否是转义后的字符*/
        function isEscapedChar(v) {
            return v === '\b' || v === '\r' || v === '\f' ||
                v === '\n' || v === '\t' || v === '\v';
        }

        /** 能作为叶子节点的类型: true false null string number */
        function isLeafType(type) {
            return (
                type === 'true' ||
                type === 'false' ||
                type === 'null' ||
                type === 'string' ||
                type === 'number'
            );
        }

        /** 在解析的JSON字符串的过程中，两个构造字符之间可以存在无意义的字符 */
        function canBeOmited(char) {
            return isEscapedChar(char) || char === ' ';
        }

        /** 解析模式类，包含解析器与它的“继任者” */
        function Mode(next) {
            this.parse = null;
            this.next = next || null;
        }

        /**
         * 逗号解析器，在它之后的解析器类型是不确定的。如果
         * 是数组元素结束，下一个解析器为值类型解析器。如果
         * 是对象属性值结束，则下一个解析器为属性名解析器
        */
        var SEP_COMMA = new Mode();

        /** 值解析器，在它之后的解析器类型是逗号解析器 */
        var VALUE = new Mode(SEP_COMMA);

        /** 值类型解析器，在它之后的解析器类型是不确定的
         * 如果值是基本数据类型的值，它的NEXT为值解析器
         * 如果值是对象类型的，它的NEXT为属性名开始标记解析器
         * 如果值是数组类型的，它的NEXT为值类型解析器
         */
        var VALUE_TYPE = new Mode();

        /** 冒号解析器，它之后的解析器一定是值类型解析器 */
        var SEP_COLON = new Mode(VALUE_TYPE);

        /**
         * 属性名解析器，它之后的解析器一定是冒号解析器。
         * 属性名结束标记在此过程中会被处理，不存在一个
         * 单独的属性名结束解析器
         */
        var KEY_NAME = new Mode(SEP_COLON);

        /** 属性名开始标记解析器，它之后的解析器一定是属性名的解析器*/
        var BEGIN_KEY = new Mode(KEY_NAME);

        /** 对象开始标记解析器，它之后的解析器一定是属性名解析器*/
        var BEGIN_OBJECT = new Mode(BEGIN_KEY);

        /** JSON字符串开始解析器，它之后的解析器一定是属性名解析器 */
        var BEGIN_JSON = new Mode(BEGIN_KEY);

        /** 用于控制解析器的转换 */
        var MODE_CHAIN = {
            tree: null,
            current: BEGIN_JSON
        };

        /** 重置当前模式为BEGIN_JSON并清空对象结构树 */
        MODE_CHAIN.initiate = function reset() {
            this.tree = null;
            this.current = BEGIN_JSON;
        }

        /**
         * 调用当前解析模式来解析参数，
         * 并返回解析成功的字符串的长度，
         * 使遍历json的索引i移动
         */
        MODE_CHAIN.parse = function parseSwtich(char, index) {
            return this.current.parse(char, this.tree, index);
        }

        /** 自动设置下一个解析模式 */
        MODE_CHAIN.next = function next() {
            this.current = this.current.next;
        }

        /** 主动设置下一个解析模式 */
        MODE_CHAIN.setNext = function setNext(next) {
            this.current = next;
        }

        /** 在遍历源JSON字符串中，需要判断哪些字符能忽略 哪些字符不能忽略 */
        function mustParse(char) {
            var mode = MODE_CHAIN.current;
            return mode == KEY_NAME || mode == VALUE || !canBeOmited(char)
        }

        /** 用来检测定界符闭合的正确性 */
        var DELIMITER_STACK = [];

        if (typeof Array.prototype.pop !== 'function') {
            DELIMITER_STACK.pop = pop;
            DELIMITER_STACK.indexSet.pop = pop;
            DELIMITER_STACK.indexSet.push = push;
        }

        /** 存放每个定界符在JSON字符串中的索引 数组 */
        DELIMITER_STACK.indexSet = [];

        /** 当定界符栈为空时，且放入过元素，说明JSON字符串匹配结束　*/
        DELIMITER_STACK.hasCompleted = false;

        /**　初始化定界符栈的数据 */
        DELIMITER_STACK.initiate = function initiate() {
            this.length = 0
            this.indexSet.length = 0;
            this.hasCompleted = false;
        }

        /**
         * 参数可能取值的范围：±(1-5)。
         *-1代表属性名的左定界符" +1代表属性名的右定界符"；
         *-2代表属性值的左定界符" +2代表属性值的右定界符"；
         *-3代表数组的左定界符[   +3代表数组的右定界符]；           
         *-4代表数组元素（字符串类型）的左定界符", +4代表数组元素的右定界符；
         *-5代表对象的左定界符{， +5代表对象的右定界符；
        */
        DELIMITER_STACK.push = function (e, index) {
            if (this.hasCompleted && len(this) === 0) {
                makeError('JSON对象解析完毕但出现多余的字符', index);
            }
            this.indexSet.push(index);
            this[this.length] = e;
            if (e > 0) { this.validate(); }
        }

        var what = ['属性名', '属性值', '数组', '数组元素', '对象'];

        /** 当放入右定界符时，进行检查定界符是否正确闭合 */
        DELIMITER_STACK.validate = function validate() {
            var first = this.pop() || 0;
            var second = this.pop() || -1;

            this.indexSet.pop();
            var si = this.indexSet.pop();

            this.hasCompleted = len(this) === 0;
            if (first + second !== 0) {
                makeError(what[first - 1] + '缺少右定界符', si);
            }
        }

        /**
         * 在JSON字符解析完成后，进行1次最终检查
         * 如果定界符栈不是空的，说明出现错误
         */
        DELIMITER_STACK.finallyCheck = function finallyCheck() {
            if (len(this) !== 0) {
                var top = Math.abs(this.pop());
                makeError(what[top - 1] + '缺少右定界符', len(json));
            }
        }

        /** 一个描述对象的树 */
        function makeStrucTree() {
            /** 基本的节点，可以不指定类型（类型将为null） */
            function Node(parent, type) {
                this.key = '';
                this.parent = parent;
                this.type = type || null;
                this.isPrimitive = null;
            }

            // 将一个不确定类型的结点给叶子化
            function LeafNode(node) {
                node.value = '';
                node.isPrimitive = true;
            }

            // 将一个不确定类型的结点分支化
            function BranchNode(node) {
                node.children = [];
                node.isPrimitive = false;
            }

            Node.prototype.writeKey = function writeKey(char) {
                this.key += char;
            }

            Node.prototype.setKey = function setKey(key) {
                this.key = key;
            }

            Node.prototype.writeValue = function writeValue(char) {
                this.value += char;
            }

            Node.prototype.setValue = function setValue(v) {
                this.value = v;
            }

            Node.prototype.setType = function setType(type) {
                this.type = type;
            }

            Node.prototype.size = function getSize() {
                return len(this.children);
            }

            Node.prototype.item = function getItem(i) {
                return this.children[i];
            }

            Node.prototype.appendChild = function appendChild(child) {
                var size = this.size();
                if (this.type === 'array') {
                    child.setKey(size);
                }
                this.children[size] = child;
            }

            // 对象描述树的思路：
            // 1、存在字符串'{"a":123, "b":456}'
            // 匹配到{时，会创建一个分支结点，并使其成为当前分支结点
            // 之后匹配到的叶子结点都会成为这个分支结点的孩子结点
            // 且把匹配到的叶子结点作为current（所有匹配到的对象属性与值写在它的上面）
            // 2、存在另一JSON字符串{"a": 123, "b": 456, "c": [a, b, c]}
            // 当匹配到[时，创建一个新的分支结点，并让其成为当前分支结点
            // 这样，abc这三个"叶子"都会被放入数组这个"分支"上
            // 如果obj还有d属性，那么d肯定是添加在obj上，而不是c这个数组结点上
            // 故而当匹配到]时，执行：this.currBranch = this.currBranch.parent。
            // 这一操纵被称为handIn
            function StructureTree() {
                this.root = null;
                this.current = null;
                this.currBranch = null;
            }

            // 不确定类型的结点 读取对象的属性名的时候会用到
            StructureTree.prototype.createNode = function cN() {
                var node = new Node(this.currBranch);
                this.currBranch.appendChild(node);
                this.current = node;
            }

            // 用于创建确定类型的叶子结点 解析到数组元素时会用到
            StructureTree.prototype.createLeafNode = function cL(type) {
                var leaf = new Node(this.currBranch, type);
                LeafNode(leaf);
                this.currBranch.appendChild(leaf);
                this.current = leaf;
            }

            // 用于创建确定类型的叶子结点 解析到数组元素时会用到
            StructureTree.prototype.createBranchNode = function cB(type) {
                var branch = new Node(this.currBranch, type);
                BranchNode(branch);
                this.currBranch.appendChild(branch);
                this.currBranch = branch;
            }

            // 创建根结点 rootTyep: array or object
            StructureTree.prototype.createRootNode = function cRoot(rootType) {
                var root = new Node(null, rootType);
                this.root = root;
                BranchNode(root);
                // 根结点一定是一个复杂类型的结点
                this.currBranch = root;
            }

            /** 给不确定类型的结点使用，将其转为确定类型的结点 */
            StructureTree.prototype.convertTo = function (target) {
                if (isLeafType(target)) this.convertToLeaf(this.current, target);
                else this.convertToBranch(this.current, target);
            }

            // 将一个不确定类型的结点转为叶子结点
            // node:不确定类型的结点 type:目标类型
            StructureTree.prototype.convertToLeaf = function ctl(node, type) {
                node.setType(type);
                LeafNode(node);
            }

            // 将一个不确定类型的结点转为分支结点
            StructureTree.prototype.convertToBranch = function ctb(node, type) {
                node.setType(type);
                BranchNode(node);
                this.currBranch = node;
            }

            /** 在发生错误时使用，删除当前叶子节点 */
            StructureTree.prototype.deleteCurr = function delC() {
                this.currBranch.children.pop();
            }

            StructureTree.prototype.handIn = function hi() {
                this.currBranch = this.currBranch.parent;
            }

            // 所有子结点都把自己的属性名与属性值交给自己的父节点
            // 父节点又作为子节点做同样的事情，root吸收所有后代节点
            // 的特征，所以称此过程为 "converge"。
            StructureTree.prototype.converge = function converge() {
                var rs = {};
                var root = this.root;
                var rs = root.type === 'array' ? [] : {};
                function recurs(parent, result) {
                    var currRs, current;
                    for (var i = 0, l = parent.size(); i < l; i++) {
                        current = parent.item(i);
                        if (current.isPrimitive) {
                            result[current.key] = current.value;
                            continue;
                        } else {
                            currRs = current.type === 'array' ? [] : {};
                            result[current.key] = recurs(current, currRs);
                        }
                    }
                    return result;
                }
                return recurs(root, rs);
            }

            return StructureTree;
        }

        var StrucTree = makeStrucTree();

        /** 存放要解析的字符串 */
        var json = '';
        /** 将JSON字符串解析成JS对象的函数 */
        function parse(str) {
            json = str;
            MODE_CHAIN.tree = new StrucTree();
            if (typeof json === 'string') {
                // [left, right]
                var closure = hasOwnClosure();
                if (isDef(closure)) {
                    // 初始化解析所需的参数
                    var left = closure[0], right = closure[1];
                    var countOfLeftWhites = len(left) - len(left.trim());
                    var countOfRightWhites = len(right) - len(right.trim());
                    var i = countOfLeftWhites;
                    var l = len(json) - countOfRightWhites;
                    if (len(left) === 2) { i++; l--; }
                } else makeError('JSON文本的开始标记与结束标记不匹配', len(json));

                var char = '';
                while (i < l) {
                    char = json.charAt(i);
                    if (mustParse(char)) {
                        i += MODE_CHAIN.parse(char, i);
                        continue;
                    }
                    i += 1;
                }
                json = '';
                DELIMITER_STACK.finallyCheck();
                var rs = MODE_CHAIN.tree.converge();
                MODE_CHAIN.initiate();
                DELIMITER_STACK.initiate();
                return rs;
            }
            throw Error('parse接收的参数必须是字符串类型的');
        }

        /** JSON字符串是否能正确闭合，正确的情况有："[JSON]" "{JSON}" [JSON] {JSON} */
        function hasOwnClosure() {
            var oneLeftStr = getLeftValidStr(1, 0),
                twoLeftStr = getLeftValidStr(2, 0),
                oneRightStr = getRightValidStr(1, 0),
                twoRightStr = getRightValidStr(2, 0);
            // "[]" 匹配右边的前2个有效字符，并拼接的时候，拼接的字符串
            // 并不是的我们看到的：]"，而是"]。这里稍作处理一下
            if (len(twoRightStr) >= 2) twoRightStr = reverse(twoRightStr);
            //结果 <     "]> -> <]"     > 尖括号是为了突显空白字符
            if ((oneLeftStr.trim() === '{' && oneRightStr.trim() === '}') ||
                (oneLeftStr.trim() === '[' && oneRightStr.trim() === ']'))
                return [oneLeftStr, oneRightStr];
            if ((twoLeftStr.trim() === '"[' && twoRightStr.trim() === ']"') ||
                (twoLeftStr.trim() === '"{' && twoRightStr.trim() === '}"'))
                return [twoLeftStr, twoRightStr];
        }

        /** 将一个字符串反转 */
        function reverse(src) {
            var rs = '';
            for (var i = len(src) - 1; i >= 0; i--) {
                rs += src.charAt(i);
            }
            return rs;
        }

        /**
         * 返回的结果以JSON字符串左右某个方向上的前n个不可以被忽略的字符为主体。在
         * 匹配的过程中，每匹配到1个空白或转义字符都会添加在返回结果的末尾。
         * 可以设置左右方向的上的起始搜索位置
         */
        function getValidStr(direction, num, begin) {
            var rs = '', char, l = len(json), i, step, whitespace = '';
            if (direction === 'left') { i = begin; step = 1; }
            else { i = l - begin - 1; step = -1; }
            for (; ; i += step) {
                if (len(rs) == num)
                    return rs + whitespace;
                if (step < 0 && i < 0)
                    break;
                if (step > 0 && i === l)
                    break;
                char = json.charAt(i);
                if (!canBeOmited(char)) {
                    rs += char;
                    continue;
                }
                whitespace += ' ';
            }
        }

        /** 获取JSON字符串左方向上前n个不可以被忽略的字符，可以设置左起点索引 */
        function getLeftValidStr(num, begin) {
            return getValidStr('left', num, begin);
        }

        /** 获取JSON字符串右方向上前n个不可以被忽略的字符，可以设置右起点索引 */
        function getRightValidStr(num, begin) {
            return getValidStr('right', num, begin);
        }

        /**
         * 当匹配到{或者[时，解析器会先判断这是否是一个空的对象或数组（它们都是JSON的一个因子）
         * 如果这个因子是空的，那么会返回这对构造符之间无效字符的数量（比如{     }，[     ]
         * 它们都是合法的JSON因子）。为什么返回这个？因为我们需要更新遍历JSON的下标i。
         */
        function hasEmptyFactory(begin, target) {
            // 获取左方向上的前两个不可以被忽略的字符，同时在尾部添加空格
            // 空格的数量：两个构造符之间无效字符的数量
            var rs = getLeftValidStr(2, begin);
            var countOfWhiteS = len(rs) - 2;
            if (rs.trim() === target) return countOfWhiteS;
        }

        /** 当isDf(hasEmptyFactory()) 为真时，会调用此方法进行处理空的JSON因子。 */
        function dealEmptyFactory(tree, factory, targetIndex) {
            tree.handIn();
            // 如果isDef(hasEmptyFactory())为真
            // 那么定界符栈必定是没有问题的，所以
            // 尾构造符}或]并不需要真实的位置。
            // 真实的位置用于确定错误文本所在的范围
            DELIMITER_STACK.push(targetIndex, 0);
            MODE_CHAIN.setNext(SEP_COMMA);
            // 空白符 + {}的长度，用于更新遍历JSON的索引I
            return factory + 2;
        }

        BEGIN_JSON.parse = function parseBeginJson(char, tree, index) {
            if (char !== '{' && char !== '[')
                makeError('JSON的开始标记匹配错误：' + char, index);
            var factory;
            if (char === '{') {
                tree.createRootNode('object');
                DELIMITER_STACK.push(-5, index);
                factory = hasEmptyFactory(index, '{}');
                if (isDef(factory))
                    return dealEmptyFactory(tree, factory, 5);
                // else 静态的同时也是必然的模式转换
                MODE_CHAIN.next();
            } else {
                tree.createRootNode('array');
                DELIMITER_STACK.push(-3, index);
                factory = hasEmptyFactory(index, '[]');
                if (isDef(factory))
                    return dealEmptyFactory(tree, factory, 3);
                MODE_CHAIN.setNext(VALUE_TYPE);
            }
            return 1;
        }

        BEGIN_OBJECT.parse = function parseBeginObject(char, tree, index) {
            if (char === '{') {
                tree.createBranchNode('object');
                DELIMITER_STACK.push(-5, index);
                var factory = hasEmptyFactory(index, '{}');
                if (isDef(factory))
                    return dealEmptyFactory(tree, factory, 5);
                MODE_CHAIN.next();
                return 1;
            }
            makeError('对象的左定界符匹配错误：' + char, index);
        }

        /**
         * 每当一个数组元素或者对象属性匹配完成后，下一个模式是 SEP_COMMA。     
         * 1、SEP_COMMA匹配完成后（匹配到了逗号），下一个模式是BEGIN_KEY
         * 或者VALUE_TYPE。在它们开始解析时，会判断有没有更多的元素。        
         * 如果有，说明刚刚匹配到的逗号没有错误。   
         * 如果没有，则说明刚刚那个逗号是多余的。
         * 
         * 2、在匹配SEP_COMMA的过程中也可能会遇到]或}，但这是正确的：
         * 没有匹配到逗号，但却匹配到了结束标记。
         * 
         * 3、两种情况的示例
         *            
         * [123, 456, 789] 9匹配完后（数组元素匹配完成后，解析器会认为还有元素），         
         * 随后解析器贪婪地取寻找逗号，但却找到了]，这说明数组结束。               
         * [123, 456, 780, false,] 最后一个逗号匹配完后，解析器认为会有更多的元素，
         * 但在之后却发现了]，解析器会认为刚才那个逗号是多余的。   
         * 
         * 4、maybe:在BEGIN_KEY、VALUE_TYPE和SEP_COMMA开始解析时都会用到这个函数        
         * 在有更多元素的情况下，只有SEP_COMMA是不报错的。maybe用来标志是否可能报错
         */
        function hasMoreElement(char, tree, index, maybe) {
            if (char === ']' || char === '}') {
                if (maybe) makeError('匹配到多余的逗号', index);
                DELIMITER_STACK.push(char === ']' ? 3 : 5, index);
                MODE_CHAIN.setNext(SEP_COMMA);
                tree.handIn();
                return 0;
            }
            return 1;
        }

        BEGIN_KEY.parse = function parseBeginKey(char, tree, index) {
            if (hasMoreElement(char, tree, index, true)) {
                if (char === '"') {
                    tree.createNode();
                    DELIMITER_STACK.push(-1, index);
                    MODE_CHAIN.next();
                } else makeError('属性名的左定界符匹配错误：' + char, index);
            }
            return 1;
        }

        KEY_NAME.parse = function parseKeyName(char, tree, index) {
            if (isEscapedChar(char)) makeError('属性名不能含有转义字符', index);
            var rs = parseString(char, tree, index);
            DELIMITER_STACK.push(1, index);
            MODE_CHAIN.next();
            tree.current.setKey(rs);
            var temp = len(rs) + 1 + countOfSlash;
            countOfSlash = 0;
            return temp;
        }

        SEP_COLON.parse = function parseSepColon(char, tree, index) {
            if (char === ':') {
                MODE_CHAIN.next();
                return 1;
            }
            makeError('冒号分隔符匹配错误：' + char, index);
        }

        /** 合理的数字头：+ - 0-9 （javascript） */
        function canBeNumHead(char) {
            return isDigit(char) || isSymbol(char);
        }

        /**
         * 在进行值类型匹配的时候，根据得到的第一个字符来确定它的类型
         * 如果它不是可能的类型，那么推测它可能是字符串的值，但是缺少
         * 字符串的开始标记了
         */
        function getValueType(char) {
            var type = abbrTypeMap[char];
            if (!type && canBeNumHead(char))
                return 'number';
            return type;
        }

        var abbrTypeMap = {
            'n': 'null',
            'f': 'false',
            't': 'true',
            '"': 'string',
            '[': 'array',
            '{': 'object'
        }

        // 在解析值前，解析器会先确定值的类型
        VALUE_TYPE.parse = function parseValueType(char, tree, index) {
            if (hasMoreElement(char, tree, index, true)) {
                var typeB = tree.currBranch.type;
                var typeC = getValueType(char);
                if (isUndef(typeC)) {
                    var target = typeB === 'array' ? '数组元素' : '对象属性';
                    makeError('未知类型的' + target + '，可能是字符串，但缺少左引号', index);
                }

                // 确定值的类型后，还需要知道它是数组元素还是属性值
                // 若是前者，需要创建一个结点，并转换它的类型
                // 若是后者，则只需转换当前节点的类型
                if (typeB === 'array') {
                    tree.createNode();
                    tree.convertTo(typeC);
                } else tree.convertTo(typeC);

                // 根据值的类型决定下一个匹配模式
                if (isLeafType(typeC)) {
                    MODE_CHAIN.setNext(VALUE);
                    if (typeC !== 'string') return 0;
                    else DELIMITER_STACK.push(typeB === 'array' ? -4 : -2, index);
                } else {
                    var targetIndex, nextMode, endIndex, targetFactory;
                    if (typeC === 'array') {
                        targetIndex = -3;
                        targetFactory = '[]';
                        nextMode = VALUE_TYPE;
                    } else {
                        targetIndex = -5;
                        targetFactory = '{}';
                        nextMode = BEGIN_KEY;
                    }
                    // 首先将左定界符放入定界符栈
                    DELIMITER_STACK.push(targetIndex, index);
                    // 判断是否是空数组或者空对象
                    var factory = hasEmptyFactory(index, targetFactory);
                    if (isDef(factory)) {
                        return dealEmptyFactory(tree, factory, -targetIndex);
                    } else MODE_CHAIN.setNext(nextMode);
                }
                return 1;
            }
        }

        VALUE.parse = function parseValue(char, tree, index) {
            if (isEscapedChar(char)) { makeError('值不能含有转义字符', index); }
            var typeC = tree.current.type;
            var typeB = tree.currBranch.type;
            MODE_CHAIN.next();
            if (typeC === 'string') {
                var rs = parseString(char, tree, index);
                DELIMITER_STACK.push(typeB === 'array' ? 4 : 2, index);
                tree.current.setValue(rs);
                var temp = len(rs) + 1 + countOfSlash;
                countOfSlash = 0;
                return temp;
            } else if (typeC === 'number') {
                return parseNumber(tree, index);
            } else {
                return parseLiteral(tree, index, typeC);
            }
        }

        /**
         * 指定一个函数类型的数组，指定json的起始遍历位置。
         * 在json索引为begin上开始，遍历len个字符，若每个字符
         * 都对位满足数组中的函数，则返回字符串本身，否则返回null。
         * len位函数类型的数组的长度
         */
        function matchByFun(fns, begin) {
            var fn, rs = '', l = len(fns);
            for (var i = 0, n = ''; i < l; i++) {
                fn = fns[i]
                n = json.charAt(begin + i);
                if (fn(n)) rs += n;
                else return null;
            }
            return rs;
        }

        /**
         * 一个字符串是否是另一个字符串的子串
         * 可以指定母子串的遍历起始位置
         */
        function matchByVal(val, begin) {
            var n = '', l = len(val);
            for (var i = 0; i < l; i++) {
                n = json.charAt(begin + i);
                if (val.charAt(i) !== n) {
                    return false;
                }
            }
            return true;
        }

        /** 字面量值true false null的解析，使用matchByVal函数 */
        function parseLiteral(tree, index, literal) {
            var value;
            switch (literal) {
                case 'null':
                    if (matchByVal('null', index))
                        value = null;
                    break;
                case 'true':
                    if (matchByVal('true', index))
                        value = true;
                    break;
                case 'false':
                    if (matchByVal('false', index))
                        value = false;
                    break;
            }
            if (value !== undefined) {
                tree.current.setValue(value);
                return len(String(value));
            }
            makeError('字面量值' + literal + '匹配错误', index);
        }

        /**
         * 解析字符串的过程中遇到的转义字符的数量               
         * 设字符串内容为：123\"，匹配的结果为 123"。
         * 原字符串内容的长度为5，但匹配到的字符串内容长度为4，
         * 它们不相等，影响了遍历json的索引i，countOfSlash用于解决这个问题。
         */
        var countOfSlash = 0;
        function parseString(char, tree, index) {
            var rs = '';
            if (char === '\\') {
                var str = parseSlash(index);
                // 因为转义字符会被忽略，匹配\"但只得到"
                var nextIndex = index + 2; // satan：index + 1
                rs += str;
                char = json.charAt(nextIndex);
                if (char === '') { makeError('字符串未能正确结束', index); }
                rs += parseString(char, tree, nextIndex);
            } else {
                if (char !== '"') {
                    rs += char;
                    char = json.charAt(++index);
                    if (char === '') { makeError('字符串未能正确结束', index); }
                    rs += parseString(char, tree, index);
                }
            }
            return rs;
        }

        /** 解析转义符号 \" 会被当成 " */
        function parseSlash(index) {
            var next = json.charAt(index + 1);
            if (next === '') { makeError('转义字符未能正确结束', index); }
            if (canBeTransferred(next)) {
                countOfSlash++;
                return next;
            } else {
                makeError(next + '无法被转义', index);
            }
        }

        /** 是否是正负号 */
        function isSymbol(v) {
            return v === '+' || v === '-';
        }

        /** 是否是科学计数法的标记E或e */
        function isE(v) {
            return v === 'E' || v === 'e';
        }

        /** 是否是1个数字，与matchByFun结合使用 */
        var condition1 = [isDigit];
        /** 是否是1个符号紧跟1个数字，与matchByFun结合使用 */
        var condition2 = [isSymbol, isDigit];
        /** E后面是否紧跟1个无符号的数字，与matchByFun结合使用 */
        var condition3 = [isE, isDigit];
        /** E后面是否紧跟1个带有符号的数字，与matchByFun结合使用 */
        var condition4 = [isE, isSymbol, isDigit];

        function parseNumber(tree, index) {
            var rs = '',
                hasMatchedDot = false,
                hasMatchedE = false;
            // 头部检查
            var validNum = matchByFun(condition1, index);
            if (isUndef(validNum))
                validNum = matchByFun(condition2, index);
            if (isUndef(validNum)) makeError('数值头部错误', index);
            else {
                rs += validNum;
                index += len(validNum);
            }

            var n = '';
            // 匹配逗号后面或E后面的 需要进行判断的字符
            var tail;
            iterate(index);
            tree.current.setValue(Number(rs));
            return len(rs);

            function iterate(i) {
                n = json.charAt(i);
                if (n === '') { makeError('数值未能正确结束', i); }
                // flag: 在递归中模拟循环中的continue
                // 若在匹配过程中匹配到了小数点或者科学计数法，需要结束本次递归，不执行后面的代码
                // 若匹配到了小数点或者科学计数法，则作特殊处理 否则一般处理
                var flag = false;
                if (!hasMatchedDot && n === '.') {
                    if (hasMatchedE) makeError('科学计数法后面不能跟小数点', i);
                    hasMatchedDot = true;
                    // 逗号后面合理的字符：1个数字或者合理的科学计数法
                    tail = matchByFun(condition1, i + 1);
                    if (isUndef(tail)) tail = matchByFun(condition3, i + 1);
                    if (isUndef(tail)) tail = matchByFun(condition4, i + 1);
                    if (tail) {
                        rs += tail;
                        i += len(tail)
                        flag = true;
                        if (!hasMatchedE) hasMatchedE = len(tail) > 1
                        iterate(i);
                    } else {
                        makeError('数值匹配错误，非法的小数部分：' + n, i);
                    }
                }

                if (flag) return;
                if (n === ',') return;

                if (!hasMatchedE && isE(n)) {
                    hasMatchedE = true;
                    // 合理的科学计数法判断
                    tail = matchByFun(condition3, i);
                    if (isUndef(tail)) tail = matchByFun(condition4, i);
                    if (tail) {
                        i += len(tail);
                        rs += tail;
                        flag = true;
                        iterate(i);
                    } else makeError('数值匹配错误，非法的科学计数法：' + n, i);
                }

                if (flag) return;
                if (n === ',') return;

                var isN = isDigit(n);
                if (!isN && n !== ']' && n !== '}') {
                    makeError('数值匹配错误，非法的数值：' + n, i);
                } else if (isN) {
                    rs += n;
                    iterate(i + 1);
                } else return;
            }
        }

        SEP_COMMA.parse = function parseCOMMA(char, tree, index) {
            // 定界符栈空的时候，代表JSON对象匹配完毕
            if (DELIMITER_STACK.length == 0) { return; }
            if (hasMoreElement(char, tree, index, false)) {
                if (char === ',') {
                    var typeB = tree.currBranch.type;
                    MODE_CHAIN.setNext(
                        typeB === 'array' ?
                            VALUE_TYPE : BEGIN_KEY
                    );
                } else makeError('逗号分隔符匹配错误（错误的转义引号字符会引发此错误）', index);
            }
            return 1;
        }

        /** 打印错误的文本区间与当前残缺的解析对象 */
        function makeError(info, index) {
            var start = Math.abs(DELIMITER_STACK.indexSet.pop()) || 0;
            if (start > 4) { start -= 4; }
            var errorText = json.substr(start, index + 6 - start);
            if (len(errorText) > 50) errorText = divide(errorText);
            if (isDef(MODE_CHAIN.tree.root)) {
                MODE_CHAIN.tree.deleteCurr();
                err('残缺的解析对象：');
                err(MODE_CHAIN.tree.converge());
            }
            err(info);
            err('错误文本区间：');
            err('<error>' + errorText + '</error>');
            throw Error('解析JSON的过程中发生错误');
        }

        /** 错误的文本区间过长时，将把它拆成3部分：head + body + tail。 */
        function divide(longStr) {
            var head = longStr.substr(0, 20);
            var body = '... ';
            var tail = longStr.substr(-20);
            return head + body + tail;
        }

        return parse;
    }

    /** 将JS对象转成JSON字符串的函数 */
    function makeStringify() {
        var _hasOwn = Object.prototype.hasOwnProperty;

        /** 对象是否拥有某个属性 */
        function hasOwn(obj, prop) {
            return _hasOwn.call(obj, prop);
        }

        function isObject(src) {
            return getRawType(src) === 'object';
        }

        function isArray(src) {
            return getRawType(src) === 'array';
        }

        /** 将JS对象转成JSON字符串的函数 */
        function stringify(src) {
            if (src === false) return 'false';
            if (src === true) return 'true';
            if (src === null) return 'null';
            if (src === undefined) return '';
            if (typeof src === 'number') return src + '';
            if (typeof src === 'function') return '';
            if (isObject(src) || isArray(src)) {
                var rs = recurs(src, '{', false);
                return rs.substring(0, len(rs) - 1);
            }
        }

        /** 输入: "123"，返回 \\\"123\\\" */
        function insertSlash(str) {
            var rs = '', char = '';
            for (var i = 0, l = len(str); i < l; i++) {
                char = str.charAt(i);
                if (canBeTransferred(char)) {
                    char = '\\' + char;
                }
                rs += char;
            }
            return rs;
        }

        function recurs(src, tag, array) {
            var rs = tag, key, items = [];
            for (key in src) {
                if (!hasOwn(src, key)) continue;
                var value = src[key];
                if (value === undefined) continue;
                var type = getRawType(value);
                // IE5不能通过getRawType得到 [object null]
                if (value === null) type = 'null';
                if (!array) {
                    key = insertSlash(key);
                    items[len(items)] = '\"' + key + '\":';
                }
                switch (type) {
                    case 'number':
                        if (isFinite(value)) items[len(items)] = value + ',';
                        break;
                    case 'boolean':
                    case 'null':
                        items[len(items)] = value + ',';
                        break;
                    case 'string':
                        items[len(items)] = '"' + insertSlash(value) + '",';
                        break;
                    case 'array':
                        items[len(items)] = recurs(value, '[', true);
                        break;
                    case 'object':
                        items[len(items)] = recurs(value, '{', false);
                        break;
                }
            }
            // 循环结束后，将最后一个匹配到的字符串末尾的,删除
            var l = len(items);
            var end = items[l - 1];
            if (end !== undefined) {
                end = end.substr(0, len(end) - 1);
                items[l - 1] = end;
            }
            for (var i = 0; i < l; i++) {
                rs += items[i];
            }
            rs += tag === '[' ? '],' : '},';
            return rs;
        }
        return stringify;

    }

    return {
        parse: makeParser(),
        stringify: makeStringify()
    }

})();